#coding: utf-8

import pygame
from pygame.locals import *

import modelagem.primitives

from modelagem.box_controls import *
from units import Plotador,InterfaceControls
from control_potencial_2d import *
from constants import *

class PlotadorEntitie(modelagem.primitives.GameObject):

	def __init__(self,id,size_x=200,size_y=200):
		super(PlotadorEntitie,self).__init__(id,PlotadorEventManager())
		
		self.image = pygame.Surface( (size_x,size_y) )
		self.image = self.image.convert()
		self.image.fill( Cor.BRANCO  )
			
		self.rect = self.image.get_rect()
		self.rect.x = 10
		self.rect.y = 10	
		
		self.unit = Plotador(size_x,size_y,self.rect)		
		
		self.mostrar_valores = True
		self.mostrar_ponto_atual = True
		
		self.mouse_x = 0
		self.mouse_y = 0
		
		self.ultimo_ponto = None
		
		
	def __limpar__(self):
		self.image.fill( Cor.BRANCO  )
		self.__criarBorda__()
		self.__criarEixo__()
		self.__desenharMarcacoes__()
	
	def __criarBorda__(self):
		pygame.draw.line(self.image,Cor.PRETO,(0,0),(self.unit.size_x-1,0) )
		pygame.draw.line(self.image,Cor.PRETO,(self.unit.size_x-1,0),(self.unit.size_x-1,self.unit.size_y-1) )
		pygame.draw.line(self.image,Cor.PRETO,(self.unit.size_x-1,self.unit.size_y-1),(0,self.unit.size_y-1) )
		pygame.draw.line(self.image,Cor.PRETO,(0,self.unit.size_y-1),(0,0) )	
		
		
	def __criarEixo__(self):
		x_origem = self.unit.origem[0]
		y_origem = self.unit.origem[1]
		
		
		pygame.draw.line(self.image,Cor.VERM,(x_origem,y_origem),(0,y_origem) )
		pygame.draw.line(self.image,Cor.VERM,(x_origem,y_origem),(self.unit.size_x-1,y_origem) )
		
		pygame.draw.line(self.image,Cor.VERM,(x_origem,y_origem),(x_origem,0) )
		pygame.draw.line(self.image,Cor.VERM,(x_origem,y_origem),(x_origem,self.unit.size_y-1) )
		
	def __desenharMarcacoes__(self):
		if not self.mostrar_valores:
			return
			
		gap_marcacao_x = self.unit.x_large/6.0
		gap_marcacao_y = self.unit.y_large/6.0
		
		x_atual = self.unit.x_minus
		y_atual = self.unit.y_minus
		
		for i in range(0,6):
			x_atual += gap_marcacao_x
			y_atual += gap_marcacao_y	
			
			x_plano,y_plano = self.unit.__getPontoNoPlano__(x_atual,0)			
			pygame.draw.line(self.image,Cor.PRETO,(x_plano,y_plano-5),(x_plano,y_plano+5) )		
			
			self.__escreverValorPonto__( (x_plano,y_plano),x_atual )
			
			x_plano,y_plano = self.unit.__getPontoNoPlano__(0,y_atual)			
			pygame.draw.line(self.image,Cor.PRETO,(x_plano-5,y_plano),(x_plano+5,y_plano) )
			
			self.__escreverValorPonto__( (x_plano,y_plano),y_atual,False )			
			
	def __escreverValorPonto__(self,pos,valor,eixo_x=True):
		if pygame.font:
			font = pygame.font.Font(None, 12)
			
		str_valor = '%(v).5g' %{'v':valor}
			
		text_valor_x = font.render( str_valor, 1, (0, 0, 0))
			
		rect_text_x = text_valor_x.get_rect()
		if eixo_x:
			rect_text_x.x = pos[0] - 15
			rect_text_x.y = pos[1] + 20
		else:
			rect_text_x.x = pos[0] - 50
			rect_text_x.y = pos[1]
			
		pygame.Surface.blit( self.image,text_valor_x,rect_text_x)			
		
		
	def __desenharPontoAtual__(self):
		if pygame.font:
			font = pygame.font.Font(None, 12)
			
			x_plano,y_plano = self.unit.__getPosNoPlano__(self.mouse_x,self.mouse_y)
			
			str_x = "x: %(x).5g"% {'x':x_plano}
			str_y = "y: %(y).5g"% {'y':y_plano}
			
			render_str_x = font.render( str_x, 1, (0, 0, 0))
			render_str_y = font.render( str_y, 1, (0, 0, 0))
										
			rect_text_x = render_str_x.get_rect()
			rect_text_x.x = self.rect.x+self.unit.size_x-50
			rect_text_x.y = self.rect.y+self.unit.size_y-50
			
			pygame.Surface.blit( self.image,render_str_x,rect_text_x)					
			
			rect_text_y = render_str_y.get_rect()
			rect_text_y.x = self.rect.x+self.unit.size_x-50
			rect_text_y.y = self.rect.y+self.unit.size_y-25
			
			pygame.Surface.blit( self.image,render_str_y,rect_text_y)	
	
	def __desenharTituloELabels__(self):
		if pygame.font:
			font = pygame.font.Font(None, 12)
			
			origem_eixo_x = self.rect.x + self.unit.size_x - 40
			origem_eixo_y = self.rect.y + 20
			
			pygame.draw.line(self.image,Cor.PRETO,(origem_eixo_x,origem_eixo_y),(origem_eixo_x+10,origem_eixo_y) )
			pygame.draw.line(self.image,Cor.PRETO,(origem_eixo_x,origem_eixo_y),(origem_eixo_x,origem_eixo_y-10) )
			
			render_str_x = font.render( self.unit.labelX, 1, (0, 0, 0))
			render_str_y = font.render( self.unit.labelY, 1, (0, 0, 0))
										
			rect_text_x = render_str_x.get_rect()
			rect_text_x.x = origem_eixo_x + 8
			rect_text_x.y = origem_eixo_y + 2
			
			pygame.Surface.blit( self.image,render_str_x,rect_text_x)					
			
			rect_text_y = render_str_y.get_rect()
			rect_text_y.x = origem_eixo_x - 7
			rect_text_y.y = origem_eixo_y -20
			
			pygame.Surface.blit( self.image,render_str_y,rect_text_y)	

			font = pygame.font.Font(None, 14)			
			
			render_titulo = font.render( self.unit.titulo, 1, (0, 0, 125))
			
			rect_text = render_titulo.get_rect()
			rect_text.x = self.rect.x
			rect_text.y = 10
			
			pygame.Surface.blit( self.image,render_titulo,rect_text)			
		
		
	def __plotar__(self,cp):
				
		for pt in cp.pontos:
			x = pt[0]
			y = pt[1]
			
			if cp.modo == PONTO:
				self.atual = self.unit.__getPontoNoPlano__(x,y)		
				pygame.draw.circle(self.image,pt.cor,self.atual,2)
			
			elif cp.modo == LINHA:
				self.atual = self.unit.__getPontoNoPlano__(x,y)
				
				#print self.ultimo_ponto,self.atual

				if self.ultimo_ponto:			
					pygame.draw.line(self.image,pt.cor,self.ultimo_ponto,self.atual)	
					
				self.ultimo_ponto = self.atual
				
			elif cp.modo == FUNCAO:
				self.atual = self.funcao.evaluar(x)
				self.atual = self.unit.__getPontoNoPlano__( self.atual[0],self.atual[1] )
				
				
				if self.ultimo_ponto:
					pygame.draw.line(self.image,pt.cor,self.ultimo_ponto,self.atual)				
					
				self.ultimo_ponto = self.atual
				
		self.ultimo_ponto = None			
		
	def update(self):	
				
		if self.unit._podePintar is True:
			if self.unit._limpar:
				self.__limpar__()
				
			if self.unit._plotar:
				for cp in self.unit.conjuntos:
					self.__plotar__(cp)
					
				if self.mostrar_ponto_atual:
					self.__desenharPontoAtual__()
					
			self.__desenharTituloELabels__()

			self.unit._podePintar = False
			self.unit._limpar = False
			self.unit._plotar = False		
			
	def gerarPlano(self,x_minus,x_large,y_minus,y_large):
		self.unit.gerarPlano(x_minus,x_large,y_minus,y_large)
		
	def limpar(self):
		self.unit.limpar()
		
	def setModo(self,modo,funcao=None):
		self.unit.setModo(modo,funcao)
		
	def setLabelX(self,labelX):
		self.unit.setLabelX(labelX)
		
	def setLabelY(self,labelY):
		self.unit.setLabelY(labelY)
		
	def setTitulo(self,titulo):
		self.unit.setTitulo(titulo)
		
	def limpar_conjuntos(self):
		self.unit.limpar_conjuntos()
		
	def iniciar_conjunto(self):
		self.unit.iniciar_conjunto()
					
	def plotar(self,pt):
		self.unit.plotar(pt)
		
	def fechar_conjunto(self):
		self.unit.fechar_conjunto()
		
		
class PlotadorEventManager(modelagem.primitives.EventManager):

	def __init__(self):
		self.mouse_in = False
		self.segura_arrastar = False
		
		self.mouse_x = 0
		self.mouse_y = 0

	def fireEvent(self,scene,go,event):
		if event.type == MOUSEBUTTONDOWN or event.type==MOUSEBUTTONUP or event.type==MOUSEMOTION:
			self.mouse_x = event.pos[0]
			self.mouse_y = event.pos[1]
			
			if go.rect.collidepoint(self.mouse_x,self.mouse_y):
				self.mouse_in = True
			
						
		if event.type == MOUSEBUTTONDOWN  and event.button == 4 and self.mouse_in:	
			go.unit.__zoom_in__()
		elif event.type == MOUSEBUTTONDOWN  and event.button == 5 and self.mouse_in:	
			go.unit.__zoom_out__()	

		elif event.type == MOUSEBUTTONDOWN and event.button == 1 and self.mouse_in:
			self.segura_arrastar = True
		elif event.type == MOUSEBUTTONUP and event.button == 1 and self.mouse_in:
			self.segura_arrastar = False
		elif event.type == MOUSEMOTION and self.mouse_in:				
			go.mouse_x=self.mouse_x
			go.mouse_y=self.mouse_y
			
			if self.segura_arrastar:
				go.unit.__move__(event.rel[0],event.rel[1])					
				
class InterfaceControlsEntitie(modelagem.primitives.GameObject):

	def __init__(self,id,plot):
		self.create_controls()
		
		controlAnalitico = ControlAnalitico(plot,self.vp_pot_placa.get_value(),1)
		controlNumerico = ControlNumerico(plot,self.vp_pot_placa.get_value(),1)
		
		self.unit = InterfaceControls(controlAnalitico,controlNumerico)
		
		self.image = self.box.image
		self.rect = self.box.rect
		
		super(InterfaceControlsEntitie,self).__init__(id,InterfaceControlsEventManager(self.vp_pot_placa))
		
		
	def create_controls(self):
		self.vp_pot_placa = VisualProperty( "Potencial placa y = 10",1)
		self.vp_pot_placa.set_value( "1" )
		
		self.vp_pot_coord_x = VisualProperty( "x",0.1 )
		self.vp_pot_coord_x.set_value( "0.1" )	
		
		self.vp_pot_coord_y = VisualProperty( "y",0.1 )
		self.vp_pot_coord_y.set_value( "0.1" )		

		self.vp_termos = VisualProperty( "Termos Fourier",1 )
		self.vp_termos.set_value( "100" )			
		
		self.vp_valor_pot = VisualProperty( "Valor Potencial no Ponto",0 )
		self.vp_valor_pot.set_value( "0" )			
		
		self.vp_modo = VisualProperty( "Modo",0 )
		self.vp_modo.set_value("ANALITICO")
		self.modo = ANALITICO
				
		self.box = BoxControls()
		self.box.add_visual_property(self.vp_pot_placa)
		self.box.add_visual_property(self.vp_pot_coord_x)
		self.box.add_visual_property(self.vp_pot_coord_y)
		self.box.add_visual_property(self.vp_valor_pot)
		self.box.add_visual_property(self.vp_termos)
		self.box.add_visual_property(self.vp_modo)
			
		self.box.create_box_control()
		self.box.rect.x = 520	
		
	def update(self):
		self.box.update()
		
		
class InterfaceControlsEventManager(modelagem.primitives.EventManager):

	def __init__(self,vp_changer):
		self.vp_changer = vp_changer
		self.inicia = 0
		
		self.segura_page_up,self.segura_page_down = False,False

	def fireEvent(self,scene,go,event):
		if event.type == KEYDOWN and event.key == K_1:
			self.vp_changer = go.vp_pot_placa
			go.vp_pot_placa.set()
			
		elif event.type == KEYDOWN and event.key == K_2:
			self.vp_changer = go.vp_pot_coord_x
			go.vp_pot_coord_x.set()
			
		elif event.type == KEYDOWN and event.key == K_3:
			self.vp_changer = go.vp_pot_coord_y
			go.vp_pot_coord_y.set()
			
		elif event.type == KEYDOWN and event.key == K_4:				
			self.vp_changer = go.vp_termos
			go.vp_termos.set()			
			
		elif event.type == KEYDOWN and event.key == K_5:
			self.vp_changer = go.vp_valor_pot
			go.vp_valor_pot.set()	
			
		elif event.type == KEYDOWN and event.key == K_t:
			if go.modo == NUMERICO:
				go.modo = ANALITICO
				go.vp_modo.set_value("Analitico")					
			else:
				go.modo = NUMERICO
				go.vp_modo.set_value("Numerico")					
				
				
		elif event.type == KEYDOWN and event.key == K_PAGEUP:		
			self.segura_page_up = True
		
			val_atual =  self.vp_changer.get_value()
			val_atual += self.vp_changer.inc
			val_atual = str(val_atual)
			
			self.vp_changer.set_value(val_atual)
			
		elif event.type == KEYDOWN  and event.key == K_PAGEDOWN:		
			self.segura_page_down = True

			val_atual = self.vp_changer.get_value()
			val_atual -= self.vp_changer.inc
			val_atual = str(val_atual)
			
			self.vp_changer.set_value(val_atual)		

		elif event.type == KEYUP  and event.key == K_PAGEDOWN:		
			self.segura_page_down = False
			inicia = 0		
			
		elif event.type == KEYUP  and event.key == K_PAGEUP:				
			self.segura_page_up = False	
			inicia = 0
			
		elif event.type == KEYDOWN and event.key == K_x:	
			if go.modo == NUMERICO:	
				go.unit.plotar_grafico_v_x_numerico( go.vp_pot_coord_y.get_value() )
			else:
				go.unit.plotar_grafico_v_x_analitico( go.vp_pot_coord_y.get_value(),go.vp_termos.get_value() )
				
		elif event.type == KEYDOWN and event.key == K_y:	
			if go.modo == NUMERICO:	
				go.unit.plotar_grafico_v_y_numerico( go.vp_pot_coord_x.get_value() )
			else:			
				go.unit.plotar_grafico_v_y_analitico( go.vp_pot_coord_x.get_value(),go.vp_termos.get_value() )		
				
		elif event.type == KEYDOWN and event.key == K_v:	
			if go.modo == NUMERICO:	
				go.unit.plotar_grafico_v_x_y_numerico()
			else:			
				go.unit.plotar_grafico_v_x_y_analitico(go.vp_termos.get_value())	
				
		elif event.type == KEYDOWN and event.key == K_e:
			if go.modo == NUMERICO:
				go.unit.plotar_campo_eletrico_numerico()				
			else:
				go.unit.plotar_campo_eletrico_analitico( go.vp_termos.get_value() )				


		if go.vp_pot_coord_y.has_changed() or go.vp_pot_coord_x.has_changed() or go.vp_termos.has_changed():	
			if go.modo == NUMERICO:
				self.atualizar_mostradores(go.vp_pot_coord_x,go.vp_pot_coord_y,go.vp_termos,go.vp_valor_pot,go.unit.controlNumerico)
			else:
				self.atualizar_mostradores(go.vp_pot_coord_x,go.vp_pot_coord_y,go.vp_termos,go.vp_valor_pot,go.unit.controlAnalitico)
				
		if self.segura_page_up:
			self.inicia+=1
			if self.inicia>30:
				val_atual = self.vp_changer.get_value()
				val_atual += self.vp_changer.inc
				val_atual = str(val_atual)				
				
				self.vp_changer.set_value(val_atual)		
			
		if self.segura_page_down:
			self.inicia+=1
			if self.inicia>30:		
				val_atual = self.vp_changer.get_value()
				val_atual -= self.vp_changer.inc
				val_atual = str(val_atual)	
				
				self.vp_changer.set_value(val_atual)						
				
			
	def atualizar_mostradores(self,vp_x,vp_y,vp_termos,vp_pot,control):
		x = vp_x.get_value()
		y = vp_y.get_value()
		_n = vp_termos.get_value()

		vp_pot.set_value( str(control.calcular_v(x,y,_n)) ) 	